package com.wiscamp.ninechapters.panels.infrastructure.repositories;


import com.wiscamp.ninechapters.panels.domain.entities.User;
import com.wiscamp.ninechapters.panels.domain.repositories.UserRepository;
import com.wiscamp.ninechapters.panels.infrastructure.converters.UserConverter;
import com.wiscamp.ninechapters.panels.infrastructure.mappers.*;
import com.wiscamp.ninechapters.panels.infrastructure.po.UserPO;
import com.wiscamp.ninechapters.panels.infrastructure.po.UserRolePO;
import com.wiscamp.ninechapters.panels.infrastructure.views.UserView;
import cube.ddd.aspect.HandleDataException;
import cube.ddd.common.query.PagedObjects;
import cube.ddd.common.query.PagedQuery;
import cube.ddd.utils.PersistenceUtils;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;

@Repository
public class UserRepositoryImpl implements UserRepository {

    private final UserMapper userMapper;

    private final UserViewMapper userViewMapper;

    private final UserRoleMapper userRoleMapper;

    private final GroupUserMapper groupUserMapper;

    private final GroupRoleMapper groupRoleMapper;

    private final RoleMenuMapper roleMenuMapper;

    private final RolePermissionMapper rolePermissionMapper;

    public UserRepositoryImpl(UserMapper userMapper, UserViewMapper userViewMapper, UserRoleMapper userRoleMapper, GroupUserMapper groupUserMapper, GroupRoleMapper groupRoleMapper, RoleMenuMapper roleMenuMapper, RolePermissionMapper rolePermissionMapper) {
        this.userMapper = userMapper;
        this.userViewMapper = userViewMapper;
        this.userRoleMapper = userRoleMapper;
        this.groupUserMapper = groupUserMapper;
        this.groupRoleMapper = groupRoleMapper;
        this.roleMenuMapper = roleMenuMapper;
        this.rolePermissionMapper = rolePermissionMapper;
    }

    private void loadDetails(User user) {
        if (Objects.nonNull(user)) {
            // 用户所在的所有用户组编号列表
            var groupIds = groupUserMapper.findGroupIdsByUser(user.getUserId());
            // 用户直接拥有的角色编号列表
            var roleIdsInUser = userRoleMapper.findRoleIdsByUser(user.getUserId());
            // 用户所在的所有用户组所拥有的角色编号列表
            var roleIdsInGroups = groupRoleMapper.findRoleIdsByGroups(groupIds);
            // 用户拥有的所有角色编号列表（包括用户组所拥有的角色编号列表）
            var roleIds = new ArrayList<Long>();
            roleIds.addAll(roleIdsInUser);
            roleIds.removeAll(roleIdsInGroups);
            roleIds.addAll(roleIdsInGroups);

            var menuIds = roleMenuMapper.findMenuIdsByRoles(roleIds);
            var permissionIds = rolePermissionMapper.findPermissionIdsByRoles(roleIds);

            user.setMenuIds(menuIds);
            user.setPermissionIds(permissionIds);
            user.setRoleIds(roleIds);
            user.setGroupIds(groupIds);
            user.setRoleIdsInUser(roleIdsInUser);
            user.setRoleIdsInGroups(roleIdsInGroups);
        }
    }

    private UserPO getUserPO(long userId) {
        return PersistenceUtils.findById(userId, userMapper::findById);
    }

    @HandleDataException
    public User getUser(long userId) {
        var user = PersistenceUtils.findEntityById(userId, userViewMapper::findById,
                UserConverter.Instance::toUserByView);
        loadDetails(user);
        return user;
    }

    @HandleDataException
    public User getUserByCode(long appId, String userCode) {
        var user = PersistenceUtils.getEntityByIdAndText(appId, userCode, userViewMapper::findByUserCode,
                UserConverter.Instance::toUserByView);
        loadDetails(user);
        return user;
    }

    @HandleDataException
    public Collection<User> getUsersByName(long appId, String userName) {
        var users = PersistenceUtils.getEntitiesByIdAndText(appId, userName, userViewMapper::findListByUserName,
                UserConverter.Instance::toUserByView);
        for (var user : users) {
            loadDetails(user);
        }
        return users;
    }

    @HandleDataException
    public Collection<User> getUsersByIds(Collection<Long> userIds) {
        var users = PersistenceUtils.getEntitiesByIds(userIds, userViewMapper::findAllById,
                UserConverter.Instance::toUserByView);
        for (var user : users) {
            loadDetails(user);
        }
        return users;
    }

    @HandleDataException
    public PagedObjects<User> getUsersByQuery(PagedQuery query) {
        PagedObjects<UserView> pagedObjects = PersistenceUtils.getPersistenceObjectsByQuery(query, userViewMapper::findAll);
        return PersistenceUtils.convertPagedObjects(pagedObjects, UserConverter.Instance::toUserByView);
    }

    @HandleDataException
    public User saveUser(User user) {
        if (user.getUserId() <= 0) {
            return PersistenceUtils.createEntity(user, userMapper::saveAndFlush,
                    UserConverter.Instance::toUserPO, UserConverter.Instance::toUser);
        } else {
            var existedPO = getUserPO(user.getUserId());
            if (existedPO == null) existedPO = new UserPO();
            return PersistenceUtils.updateEntity(user, existedPO, userMapper::saveAndFlush,
                    UserConverter.Instance::toUserPO, UserConverter.Instance::toUser);
        }
    }

    @HandleDataException
    public boolean bindUserRole(long userId, long roleId) {
        var userRoles = userRoleMapper.findByUserAndRole(userId, roleId);
        if (userRoles == null) {
            userRoles = new UserRolePO();
            userRoles.setUserId(userId);
            userRoles.setRoleId(roleId);
            userRoleMapper.saveAndFlush(userRoles);
        }
        return true;
    }

    @HandleDataException
    public boolean unbindUserRole(long userId, long roleId) {
        var userRoles = userRoleMapper.findByUserAndRole(userId, roleId);
        if (userRoles != null) {
            userRoleMapper.delete(userRoles);
        }
        return true;
    }
}
